package com.ihr360.expr.function.excel;


import com.ihr360.expr.ExprArray;
import com.ihr360.expr.ExprError;
import com.ihr360.expr.ExprException;
import com.ihr360.expr.context.IEvaluationContext;
import com.ihr360.expr.core.AbstractFunction;
import com.ihr360.expr.core.Expr;
import com.ihr360.expr.core.ExprFunction;
import com.ihr360.expr.core.ExprVariable;
import com.ihr360.expr.utils.ExprUtils;

/**
 * HLOOKUP(search_criteria,array,index,sorted)
 */
public class HLOOKUP extends AbstractFunction {
    @Override
    public Expr evaluate(IEvaluationContext context, Expr[] args)
            throws ExprException {
        assertMinArgCount(args, 3);
        assertMaxArgCount(args, 4);
        return arrayLookup(context, args);

    }


    public Expr arrayLookup(IEvaluationContext context, Expr[] args) throws ExprException {
        Expr ev = ExprUtils.evalArg(context, args[0]);
        int index = asInteger(context, args[2], true);
        Expr array = args[1];
        if (array instanceof ExprVariable) {
            array = ExprUtils.evalArg(context, array);
        }
        if (array instanceof ExprArray) {
            ExprArray exprArray = (ExprArray) array;
            if (index > exprArray.rows()) {
                return ExprError.INDEX_RANGE;
            }
            int colSize = exprArray.columns();
            int col;
            int hitCol = -1;
            int lastCompare = Integer.MIN_VALUE;
            for (col = 0; col < colSize; col++) {
                Expr expr = exprArray.get(0, col);
                if (expr instanceof ExprFunction) {
                    expr = ExprUtils.evalArg(context, expr);
                }
                int compare = ExprUtils.compareToNotStrict(context, ev, expr);
                if (compare == 0) {
                    hitCol = col;
                    break;
                }
                if (lastCompare != Integer.MIN_VALUE && compare < 0) {
                    //if (lastCompare>0 && lastCompare!=Integer.MIN_VALUE && compare<0){
                    hitCol = col - 1;
                    break;
                }
                if (compare > 0 && col == colSize - 1) {
                    hitCol = colSize - 1;
                    break;
                }
                lastCompare = compare;
            }
            if (colSize == 1) {
                hitCol = 0;
            }
            if (hitCol >= 0) {
                Expr expr = exprArray.get(index - 1, hitCol);
                if (expr instanceof ExprFunction) {
                    expr = ExprUtils.evalArg(context, expr);
                }
                return expr;
            }
        }
        return ExprError.VALUE;
    }
}
